import os
import logging
from typing import Dict, Any, Optional
from uvicorn.config import LOGGING_CONFIG
import logging.handlers

# 普通log初始化配置
class LoggerConfig:
    def __init__(
        self,
        log_dir: str = "logs",
        log_filename: str = "app.log",
        log_level: str = "INFO",
        max_bytes: int = 10 * 1024 * 1024,  # 10MB
        backup_count: int = 5,
        console_log: bool = True,
        docker_mode: bool = False
    ):
        """
        初始化日志配置
        
        :param log_dir: 日志目录
        :param log_filename: 日志文件名
        :param log_level: 日志级别 (DEBUG, INFO, WARNING, ERROR, CRITICAL)
        :param max_bytes: 单个日志文件最大大小
        :param backup_count: 备份日志文件数量
        :param console_log: 是否同时输出到控制台
        :param docker_mode: 是否为Docker模式（会调整日志路径和格式）
        """
        self.log_dir = log_dir if log_dir else "logs"
        self.log_filename = log_filename if log_filename else "app.log"
        log_level = log_level if log_level else "INFO"
        self.log_level = self._get_log_level(log_level)
        self.max_bytes = int(max_bytes) if max_bytes else 10 * 1024 * 1024
        self.backup_count = int(backup_count) if backup_count else 5
        self.console_log = console_log
        self.docker_mode = docker_mode
        
        # 确保日志目录存在
        os.makedirs(self.log_dir, exist_ok=True)
        
        
        # 日志格式
        self.log_format = logging.Formatter(
            '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
        )
        
        # 初始化根日志器
        self.root_logger = logging.getLogger()
        self.root_logger.setLevel(self.log_level)
        
        # 清除已存在的处理器，避免重复输出
        self.root_logger.handlers = []
        
        # 添加文件处理器
        self._add_file_handler()
        
        # 添加控制台处理器（如果启用）
        if self.console_log:
            self._add_console_handler()

    def _get_log_level(self, level_str: str) -> int:
        """将字符串日志级别转换为logging模块对应的整数级别"""
        level_map = {
            "DEBUG": logging.DEBUG,
            "INFO": logging.INFO,
            "WARNING": logging.WARNING,
            "ERROR": logging.ERROR,
            "CRITICAL": logging.CRITICAL
        }
        return level_map.get(level_str.upper(), logging.INFO)
   

    def _add_file_handler(self) -> None:
        """添加文件日志处理器"""
        log_file_path = os.path.join(self.log_dir, self.log_filename)
        
        # 使用RotatingFileHandler实现按大小切割日志
        file_handler = logging.handlers.RotatingFileHandler(
            log_file_path,
            maxBytes=self.max_bytes,
            backupCount=self.backup_count,
            encoding='utf-8'
        )
        file_handler.setFormatter(self.log_format)
        file_handler.setLevel(self.log_level)
        
        self.root_logger.addHandler(file_handler)

    def _add_console_handler(self) -> None:
        """添加控制台日志处理器"""
        console_handler = logging.StreamHandler()
        console_handler.setFormatter(self.log_format)
        console_handler.setLevel(self.log_level)
        
        self.root_logger.addHandler(console_handler)

    @classmethod
    def from_env(cls) -> 'LoggerConfig':
        """从环境变量加载日志配置，适合Docker环境"""
        return cls(
            log_dir=os.getenv("LOG_DIR", "logs"),
            log_filename=os.getenv("LOG_FILENAME", "app.log"),
            log_level=os.getenv("LOG_LEVEL", "INFO"),
            max_bytes=os.getenv("LOG_MAX_BYTES", 10 * 1024 * 1024),
            backup_count=os.getenv("LOG_BACKUP_COUNT", 5),
        )


# 使用示例
def get_logger(name: Optional[str] = None) -> logging.Logger:
    """获取配置好的日志器实例"""
    return logging.getLogger(name)



# uvicorn log初始化配置
# 通常在应用启动时调用一次
def init_logger():
    # 优先从环境变量加载配置，方便Docker环境配置
    LoggerConfig.from_env()


def customize_uvicorn_logging(
    log_dir: str = "logs",
    log_filename: str = "app.log",
    log_level: str = "INFO",
    max_bytes: int = 10 * 1024 * 1024,  # 10MB
    backup_count: int = 5,
    # 自定义日志格式，包含时间、日志器、级别和消息
    log_format: str = "%(asctime)s - %(levelname)s - %(message)s",
    date_format: str = "%Y-%m-%d %H:%M:%S"
) -> Dict[str, Any]:
    """
    定制Uvicorn日志配置：
    1. 修改日志输出格式
    2. 同时输出到控制台（保留原有功能）和指定文件
    3. 支持日志轮转和中文输出
    """
    log_dir = log_dir if log_dir else "logs"
    log_filename = log_filename if log_filename else "app.log"
    log_level = log_level if log_level else "INFO"
    max_bytes = int(max_bytes) if max_bytes else 10 * 1024 * 1024
    backup_count = int(backup_count) if backup_count else 5
    # 确保日志目录存在
    if log_dir and not os.path.exists(log_dir):
        os.makedirs(log_dir, exist_ok=True)
    log_file = os.path.join(log_dir, log_filename)
    # 复制Uvicorn默认日志配置作为基础
    log_config = LOGGING_CONFIG.copy()
    
    # 1. 修改日志格式 - 应用于控制台和文件输出
    log_config["formatters"]["default"] = {
        "format": log_format,
        "datefmt": date_format
    }
    # 访问日志格式也使用相同配置
    log_config["formatters"]["access"] = {
        "format": log_format,
        "datefmt": date_format
    }
    
    # 2. 添加文件日志处理器
    log_config["handlers"]["file"] = {
        "class": "logging.handlers.RotatingFileHandler",
        "formatter": "default",  # 使用上面定义的格式
        "filename": log_file,
        "maxBytes": max_bytes,   # 单个文件最大大小
        "backupCount": backup_count,  # 备份文件数量
        "encoding": "utf-8"      # 支持中文
    }
    
    
    # 3. 更新日志器配置：同时使用控制台和文件处理器
    # 更新主日志器
    log_config["loggers"]["uvicorn"]["handlers"] = ["default", "file"]
    # 更新错误日志器
    log_config["loggers"]["uvicorn.error"]["handlers"] = ["default", "file"]
    log_config["loggers"]["uvicorn.error"]["propagate"] = False
    # 更新访问日志器
    log_config["loggers"]["uvicorn.access"]["handlers"] = ["access", "file"]
    log_config["loggers"]["uvicorn.access"]["propagate"] = False
    
    # 4. 设置日志级别
    log_level_upper = log_level.upper()
    log_config["loggers"]["uvicorn"]["level"] = log_level_upper
    log_config["loggers"]["uvicorn.error"]["level"] = log_level_upper
    log_config["loggers"]["uvicorn.access"]["level"] = log_level_upper
    
    return log_config


# 从环境变量加载配置的便捷函数
def get_uvicorn_log_config() -> Dict[str, Any]:
    """从环境变量获取配置，方便在不同环境中使用"""
    return customize_uvicorn_logging(
        log_dir=os.getenv("LOG_DIR", "logs"),
        log_filename=os.getenv("LOG_FILENAME", "app.log"),
        log_level=os.getenv("LOG_LEVEL", "INFO"),
        max_bytes=os.getenv("LOG_MAX_BYTES", 10 * 1024 * 1024),
        backup_count=os.getenv("LOG_BACKUP_COUNT", 5)
    )
    
